package cn.tedu.charging.device.canal;

import cn.tedu.charging.device.pojo.StationCanalPO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import top.javatool.canal.client.annotation.CanalTable;
import top.javatool.canal.client.handler.EntryHandler;

import java.util.concurrent.*;

/**
 * 场站数据库数据和Redis数据同步处理器
 * 数据库表 charging_station 如果发生了变化 C create 创建 U update 更新 D delete 删除
 * 要通知 StationSyncHandler 处理器
 *
 * charging_station 插入了数据 C 通知 StationSyncHandler#insert 方法  在Redis插入数据
 * charging_station 更新了数据 U 通知 StationSyncHandler#update 方法  在Redis更新数据
 * charging_station 删除了数据 D 通知 StationSyncHandler#delete 方法  在Redis删除数据
 *
 *
 * @CanalTable("charging_station")
 */
@Slf4j
@Component
@CanalTable("charging_station")
public class StationSyncHandler implements EntryHandler<StationCanalPO> {

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * charging_station 插入了数据 C
     * 通知 StationSyncHandler#insert 方法  在Redis插入数据
     * @param stationCanalPO
     */
    @Override
    public void insert(StationCanalPO stationCanalPO) {
        log.debug("数据表 charging_station 插入了新的数据:{}", stationCanalPO);
        log.debug("通过RedisTemplate <插入> 场站的数据 ");
        //todo 自己查询对应类型的 插入API String 插入 Hash插入
        // put add set 没有就保存，有就更新
        // 可以参考 缓存预热 预热就是保存动作
        EntryHandler.super.insert(stationCanalPO);
    }

    /**
     * charging_station 更新了数据 U
     * 通知 StationSyncHandler#update 方法  在Redis更新数据
     * @param before
     * @param after
     */
    @Override
    public void update(StationCanalPO before, StationCanalPO after) {
        log.debug("数据表 charging_station 更新了数据,更新之前:{}，更新之后:{}", before, after);
        log.debug("通过 RedisTemplate <更新> 场站的数据 ");
        //todo 自己查询对应类型的 更新API String 如何更新 Hash如何更新
        //put add set 没有就保存，有就更新
        //String key 站点id value StationPO
        ValueOperations valueOperations = redisTemplate.opsForValue();
        String key = "station_info_string_" + after.getId();
        //全量覆盖 StationCanalPO 有很多的字段，管理员只更新一个字段或者部分字段
        //通过Canal更新的时候 用String类型 set 全部更新
        //在StationCanalPO 字段少的时候问题不大
        //如果 在StationCanalPO 更新的对象 有很多字段 全部更新 把没变化也更新了 浪费资源
        valueOperations.set(key,after);

        //Hash  key  站点id 小key 属性名称  value 属性值
        //更新的时候 怎么更新？
        HashOperations hashOperations = redisTemplate.opsForHash();
        String bigKey = "station_info_hash_no_share_" + after.getId();
        //把更新之后的after PO 转换为Map 直接put bigKey 存在就更新 全量覆盖
        //通过Canal更新的时候 用Hash类型 putALl 全部更新
        //在 StationCanalPO 字段少的时候问题不大
        //如果 在StationCanalPO 更新的对象 有很多字段 全部更新 把没变化也更新了 浪费资源
        //hashOperations.putAll(bigKey,);
        //put(bigKey,key,after) hash类型 可以 只更新部分值
        //比较 before 和 after 变化 把变化的值更新 只更新了name
        //String 更新后的名称 = after.getName();
        //hashOperations.put(bigKey,"name",更新后的名称);
        EntryHandler.super.update(before, after);
    }

    /**
     * charging_station 删除了数据 D
     * 通知 StationSyncHandler#delete 方法  在Redis删除数据
     * @param stationCanalPO
     */
    @Override
    public void delete(StationCanalPO stationCanalPO) {
        log.debug("数据表 charging_station 删除了数据{}",stationCanalPO);
        log.debug("通过RedisTemplate <删除> 场站的数据 ");
        //todo 自己查询api删除数据 通过key del
        //String key = "station_info_string_" + stationCanalPO.getId();
        //redisTemplate.delete(key);
        //String bigKey = "station_info_hash_no_share_" + stationCanalPO.getId();
        //redisTemplate.delete(bigKey);
        EntryHandler.super.delete(stationCanalPO);

        ExecutorService executorService = Executors.newCachedThreadPool();
        BlockingQueue  queue = new ArrayBlockingQueue(10);

    }
}
